﻿using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
using System.Web;
using Synology.DS.Interface.Abstract;

namespace Synology.DS.Core
{
    public class WebClientEx : WebClient, IWebClient
    {
        private readonly CookieContainer _cookiesContainer;

        public WebClientEx()
        {
            _cookiesContainer = new CookieContainer();
            Encoding = Encoding.GetEncoding(1251);
        }

        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest request = base.GetWebRequest(address);
            if (request is HttpWebRequest)
            {
                (request as HttpWebRequest).CookieContainer = _cookiesContainer;
            }
            return request;
        }

        protected override WebResponse GetWebResponse(WebRequest request)
        {
            //return base.GetWebResponse(request);
            WebResponse response = base.GetWebResponse(request);

            if (response is HttpWebResponse)
            {
                HttpWebResponse webResponse = response as HttpWebResponse;
                _cookiesContainer.Add(webResponse.Cookies);
            }

            return response;
        }

        public byte[] UploadBinaryValues(string address, NameValueCollection data)
        {
            return base.UploadValues(address, data);
        }

        public string Post(string url, object request)
        {
            return Submit(url, "POST", request);
        }

        public string Get(string url, object request)
        {
            string getUrl = string.Format("{0}?{1}", url, GetQueryStringFromObject(request));
            byte[] data = DownloadData(getUrl);
            return Encoding.ASCII.GetString(data);
        }

        private string Submit(string url, string method, object request)
        {
            HttpWebRequest webRequest = (HttpWebRequest)GetWebRequest(new Uri(url));
            webRequest.Method = method;
            webRequest.KeepAlive = true;

            using (var SW = new StreamWriter(webRequest.GetRequestStream()))
            {
                SW.Write(GetQueryStringFromObject(request));
                SW.Flush();
                using (WebResponse response = webRequest.GetResponse())
                using (StreamReader SR = new StreamReader(response.GetResponseStream()))
                {
                    return SR.ReadToEnd();
                }
            }
        }

        private string GetQueryStringFromObject(object obj)
        {
            if (obj == null)
                return null;

            StringBuilder result = new StringBuilder();
            PropertyInfo[] properties = obj.GetType().GetProperties();
            foreach (PropertyInfo property in properties)
            {
                object value = property.GetValue(obj, null);
                result.AppendFormat("{0}={1}", property.Name, value == null ? string.Empty : HttpUtility.HtmlEncode(value.ToString()));
                result.Append("&");
            }

            result.Remove(result.Length - 1, 1);
            return result.ToString();
        }
    }
}
